package com.tian.arch.function.adapter.core

import android.content.Context
import android.util.SparseArray
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncListDiffer
import com.tian.arch.function.adapter.*
import com.tian.arch.function.adapter.diff.DefaultDiffCallback
import com.tian.arch.function.adapter.diff.LiteDiffUtil
import com.tian.arch.util.onClick


/**
 *  轻量级adapter
 */
open class LiteAdapter<T>(private val context: Context) : AbsAdapter<T>(context) {

    /**
     *  viewBinder集合，key为 viewType,value:viewBinder
     */
    private val viewBinders by lazy { SparseArray<ViewBinder<T>>() }

    /**
     * 只有在多布局类型时使用
     */
    private var viewTypeFinder: ViewTypeFinder<T>? = null

    private var onItemClickListener: OnItemClickListener<T>? = null
    private var onItemLongClickListener: OnItemLongClickListener<T>? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binder = requireNotNull(viewBinders[viewType]) {
            "u must registered this viewType=$viewType"
        }
        val itemView = LayoutInflater.from(context).inflate(binder.layoutId, parent, false)
        val holder = ViewHolder(itemView)

        itemView.apply {
            onClick {
                val position = holder.layoutPosition
                onItemClickListener?.invoke(position, dataSet[position])
            }

            setOnLongClickListener {
                val position = holder.layoutPosition
                onItemLongClickListener?.invoke(position, dataSet[position])
                true
            }
        }
        return holder
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = dataSet[position]
        val binder = viewBinders[getViewType(position)]
        requireNotNull(binder) {
            "u must register this view type binder ${getViewType(position)}"
        }
        binder.bind(holder, item, position)
    }

    override fun getItemCount() = dataSet.size

    override fun getItemViewType(position: Int) = getViewType(position)

    private fun getViewType(position: Int): Int {
        if (viewBinders.size() <= 1) return 0
        requireNotNull(viewTypeFinder) {
            "please register ViewType Finder"
        }
        return viewTypeFinder!!.getViewType(position, dataSet[position])
    }

    private fun innerRegisterBinder(viewType: Int? = 0, binder: ViewBinder<T>) {
        viewBinders.put(viewType ?: 0, binder)
    }

    /**
     *  注册 布局绑定器
     */
    fun register(layoutId: Int, viewType: Int? = 0, bindBlock: (holder: ViewHolder, item: T, position: Int) -> Unit) {
        innerRegisterBinder(
            viewType ?: 0,
            object : ViewBinder<T>(layoutId) {
                override fun bind(holder: ViewHolder, item: T, position: Int) {
                    bindBlock(holder, item, position)
                }
            }
        )
    }

    /**
     *  注册viewType 值获取器
     */
    fun registerViewTypeFinder(finder: ViewTypeFinder<T>) {
        this.viewTypeFinder = finder
    }

    fun itemClickListener(listener: OnItemClickListener<T>) {
        this.onItemClickListener = listener
    }

    fun itemLongClickListener(listener: OnItemLongClickListener<T>) {
        this.onItemLongClickListener = listener
    }

    open fun autoDiff(diffCallback: LiteDiffUtil.Callback? = DefaultDiffCallback()) {
        this.diffCallback = diffCallback
    }

    companion object {

        /**
         * 创建adapter的方法
         */
        fun <T> create(context: Context, initializer: LiteAdapter<T>.() -> Unit): LiteAdapter<T> {
            return LiteAdapter<T>(context).apply(initializer)
        }
    }

}